每位後端RD, 在寫WebAPI時,
一定覺得寫扣還要維護API文件, 是件很繁瑣但又重要的工作.
不寫, 前端或者串接的人照三餐來問.
寫, 又很花時間還容易寫錯字.
Swagger是一個能夠快速的生產出一份API Doc的工具.
幾乎主流語言都有支援Swagger, Go也不例外.
Swaggo/swag就是用Go撰寫的.
swag有支援gin、net/http, 剛好我們前面寫的都能用^^
go get -u github.com/swaggo/swag/cmd/swag
檢查swag, 會出現版本跟指令
其實也就init跟help
swag -h
在專案根目錄下執行
swag init
會看到在根目錄下生出了doc資料夾, 裡面會有
首先匯入docs包, mod名稱請改成自己的^^
小小修改一下code, SetupRouter傳入port這參數.
router也改成監聽port提供的端口.
test那邊的案例, 記得都要傳入隨便一個數字, 不然測試會跑失敗.
main.go
import (
_ "github.com/tedmax100/gin-angular/docs"
)
func main() {
port := 8080
router := router.SetupRouter(port)
router.Run(fmt.Sprintf(":%d", port))
}
SetupRouter.go
import (
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)
func SetupRouter(port int) *gin.Engine {
...
if mode := gin.Mode(); mode == gin.DebugMode {
url := ginSwagger.URL(fmt.Sprintf("http://localhost:%d/swagger/doc.json", port))
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
}
...
}
因為Swagger幾乎都是在內部網路可視的.
不然外網要是也能看得到...就都能亂打API了.
這個就把http監聽的port傳進來.
也判別gin.Mode()是不是處於debug mode.
是的話才註冊swagger要用的路由.
Swagger能產文件, 其實全靠註解.
只要遵從swagger格式寫出來的註解, 就會產生對應文檔說明.
main.go
// @title Gin swagger
// @version 1.0
// @description Gin swagger
// @contact.name nathan.lu
// @contact.url https://tedmax100.github.io/
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:8080
// schemes http
func main() { ... }
註解 | 描述 |
---|---|
title | 必須 簡單API專案的標題或主要的業務功能 |
version | 必須 目前這專案/API的版本 |
description | 簡單描述 |
tersOfService | 服務條款 |
contact.name | 作者名稱 |
contact.url | 作者blog |
contact.email | 作者email |
license.name | 必須 許可證名稱 |
license.url | 許可證網址 |
host | 服務名稱或者是ip |
BasePath | 基本URL路徑, (/api/v1, /v2...) |
schemes | 提供的協定, (http, https) |
執行生成api doc, 並且執行api
swag init; go run main.go
打開瀏覽器輸入http://localhost:8080/swagger/index.html
如果都沒錯誤, 看到的就是這樣, 空的XD
因為還沒對每隻API寫註解.
helloHandler.go
// @Summary 說Hello
// @Id 1
// @Tags Hello
// @version 1.0
// @produce text/plain
// @Success 200 string string 成功後返回的值
// @Router /hello [get]
func GetHello(ctx *gin.Context) {...}
// @Summary Delete Hello
// @Id 1
// @Tags Hello
// @version 1.0
// @produce text/plain
// @param id path int true "id"
// @Success 200 string string 成功後返回的值
// @Router /hello/{id} [delete]
func DeleteHello(ctx *gin.Context) { ... }
userHandler.go
在這裡新增自定義的Header, 通常我們就是放authorization token用
或其他, 只要標示是在header即可.
// @Summary User Login
// @Tags User
// @version 1.0
// @produce application/json
// @param email formData string true "email"
// @param password formData string true "password"
// @param password-again formData string true "password-again"
// @Success 200 string string 成功後返回的值
// @Router /user/login [post]
func UserLogin(ctx *gin.Context) { ... }
// @Summary Get User Info
// @Tags User
// @version 1.0
// @produce text/plain
// @param Authorization header string true "Authorization"
// @param uid path int true "uid"
// @Success 200 string string 成功後返回的值
// @Router /user/{uid} [get]
func GetUser(ctx *gin.Context) { ... }
註解 | 描述 |
---|---|
summary | 描述該API |
tags | 歸屬同一類的API的tag |
accept | request的context-type |
produce | response的context-type |
param | 參數按照 參數名 參數類型 參數的資料類型 是否必須 註解 (中間都要空一格) |
header | response header return code 參數類型 資料類型 註解 |
router | path httpMethod |
再次執行生成api doc, 並且執行api
swag init; go run main.go
打開瀏覽器輸入http://localhost:8080/swagger/index.html
基本的API文件就出來了
但我還是覺得單元測試跟整合測試寫的完整點, 比較實在XD
畢竟文件只能是串接開發時參考用, 測試才能一直重複利用.
好的測試本身就是個能讀的文件(BDD).